package util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Base64;

import androidx.annotation.StringDef;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import lombok.NonNull;

public class BitmapUtil {

    public static String getSDPath() {
        boolean sdCardExist = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
        if (sdCardExist) {
            return Environment.getExternalStorageDirectory().getPath();
        } else {
            return "";
        }
    }

    /**
     * 将图片转换成Base64编码的字符串
     *
     * @param path Bitmap的全路径
     */
    public static String bitmap2Base64(String path) {
        if (TextUtils.isEmpty(path)) {
            return null;
        }
        InputStream is = null;
        byte[] data = null;
        String result = null;
        try {
            is = new FileInputStream(path);
            //创建一个字符流大小的数组。
            data = new byte[is.available()];
            //写入数组
            is.read(data);
            //用默认的编码格式进行编码
            result = Base64.encodeToString(data, Base64.NO_CLOSE);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return result;
    }

    /**
     * 将Base64编码字符串转为图片
     *
     * @param base64Str 源编码的Base64字符串
     * @return bitmap
     */
    public static Bitmap base64ToBitmap(String base64Str) {
        byte[] data = Base64.decode(base64Str, Base64.NO_WRAP);
        if (data != null && data.length > 0) {
            for (int i = 0; i < data.length; i++) {
                if (data[i] < 0) {
                    //调整异常数据
                    data[i] += 256;
                }
            }
            return BitmapFactory.decodeByteArray(data, 0, data.length);
        }
        return null;
    }

    /**
     * 将Base64编码转换为Bitmap 并保存
     *
     * @param base64Str 源编码的Base64字符串
     * @param parentDir Bitmap保存的父目录路径
     * @param name      Bitmap 的名称，不需要带上后缀
     * @return Bitmap的全路径名称
     */
    public static String base64ToBitmap(String base64Str, String parentDir, String name, @ImageType String type) {
        String path = "";
        byte[] data = Base64.decode(base64Str, Base64.NO_WRAP);
        for (int i = 0; i < data.length; i++) {
            if (data[i] < 0) {
                //调整异常数据
                data[i] += 256;
            }
        }
        OutputStream os = null;
        try {
            File parentFile = new File(parentDir);
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            } else {
                if (getFileSize(parentFile) > 1024 * 1024 * 50) {
                    deleDir(parentDir);
                }
            }
            File jpgFile = new File(parentDir, name + type);
            os = new FileOutputStream(jpgFile);
            os.write(data);
            os.flush();
            path = jpgFile.getAbsolutePath();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return path;
    }

    public static byte[] bitmap2Bytes(Bitmap bitmap) {
        ByteArrayOutputStream byteArrOutStream = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrOutStream);
        return byteArrOutStream.toByteArray();
    }

    public static Bitmap bytes2Bitmap(@NonNull byte[] bytes) {
        if (bytes.length != 0) {
            return BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
        }
        return null;
    }

    public static Bitmap compressionBitmap(@NonNull Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        if (baos.toByteArray().length / 1024 > 2048) {
            baos.reset();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 60, baos);
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        newOpts.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(isBm, null, newOpts);
        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        int be = 1;
        if (w > h && ((float) w) > 1280.0f) {
            be = (int) (((float) newOpts.outWidth) / 1280.0f);
        } else if (w < h && ((float) h) > 720.0f) {
            be = (int) (((float) newOpts.outHeight) / 720.0f);
        }
        if (be <= 0) {
            be = 1;
        }
        newOpts.inSampleSize = be;
        newOpts.inPreferredConfig = Bitmap.Config.RGB_565;
        return BitmapFactory.decodeStream(new ByteArrayInputStream(baos.toByteArray()), null, newOpts);
    }

    /**
     * 将原始的位图数据的bytes 保存到指定路径下
     *
     * @param data
     * @param parentDir Bitmap保存的父目录路径
     * @param name      Bitmap 的名称，不需要带上后缀
     * @return Bitmap的全路径名称
     */
    public static void save2SDCard(byte[] data, String parentDir, String name, @ImageType String type) {
        FileOutputStream outputStream = null;
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        String dateStr = df.format(new Date());
        String photoName = "qr_" + dateStr;
        try {
            File parentFile = new File(parentDir);
            if (!parentFile.exists()) {
                parentFile.mkdirs();
            }
            File jpgFile = new File(parentDir, photoName + type);
            outputStream = new FileOutputStream(jpgFile); // 文件输出流

//            BASE64Decoder decoder = new BASE64Decoder();
//            try {
//                // Base64解码
//                byte[] bytes = decoder.decodeBuffer(imgStr.substring(22));
//
//                System.out.println("bytes的长度:"+bytes.length);
//
//                for (int i = 0; i < bytes.length; ++i) {
//                    if (bytes[i] < 0) {// 调整异常数据
//                        bytes[i] += 256;
//                    }
//                }
//                // 生成jpg图片
//                OutputStream out = new FileOutputStream(imgFilePath+imgFileName);
//                out.write(bytes);
//                out.flush();
//                out.close();
//            } catch (Exception e) {
//
//            }

            outputStream.write(data); // 写入sd卡中
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close(); // 关闭输出流
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static boolean fileExits(String fileName) {
        return (fileName == null || "".equals(fileName) || !new File(fileName).exists()) ? false : true;
    }

    public static boolean deleteFile(String fileName) {
        File file = new File(fileName);
        if (fileExits(fileName)) {
            return file.delete();
        }
        return false;
    }

    public static boolean deleDir(String dirName) {
        if (!fileExits(dirName)) {
            return false;
        }
        File dir = new File(dirName);
        File[] tmp = dir.listFiles();
        for (int i = 0; i < tmp.length; i++) {
            if (tmp[i].isDirectory()) {
                deleDir(dirName + "/" + tmp[i].getName());
            } else {
                tmp[i].delete();
            }
        }
        return dir.delete();
    }

    public static long getFileSize(File f) {
        long size = 0;
        File flist[] = f.listFiles();
        for (int i = 0; i < flist.length; i++) {
            if (flist[i].isDirectory()) {
                size = size + getFileSize(flist[i]);
            } else {
                size = size + flist[i].length();
            }
        }
        return size;
    }

    public static class MD5{
        /**
         * 根据图片路径获取MD5
         * @param imagePath
         * @return
         */
        public static String getFileMD5(String imagePath) {
            String ret="";
            if (!TextUtils.isEmpty(imagePath)) {
                File file = new File(imagePath);
                if(file.exists()) {
                    InputStream in=null;
                    StringBuilder md5 = new StringBuilder();
                    try {
                        MessageDigest md = MessageDigest.getInstance("MD5");
                        in= new FileInputStream(file);
                        int n = 0;
                        byte[] dataBytes = new byte[1024];
                        while ((n = in.read(dataBytes)) != -1) {
                            md.update(dataBytes, 0, n);
                        }
                        byte[] bytes = md.digest();
                        for (int i = 0; i < bytes.length; i++) {
                            md5.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1));
                        }
                        ret=md5.toString().toUpperCase();
                    } catch (NoSuchAlgorithmException | IOException e) {
                        e.printStackTrace();
                    } finally {
                        if(in!=null){
                            try {
                                in.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }
            return ret;
        }

        /**
         * 获取字符串对应的MD5
         * @param str
         * @return
         */
        public static String getStrMD5(String str) {
            String ret="";
            if (!TextUtils.isEmpty(str)) {
                try {
                    MessageDigest md5 = MessageDigest.getInstance("MD5");
                    char[] charArray = str.toCharArray();
                    byte[] byteArray = new byte[charArray.length];
                    for (int i = 0; i < charArray.length; i++) {
                        byteArray[i] = (byte) charArray[i];
                    }
                    byte[] md5Bytes = md5.digest(byteArray);
                    StringBuilder hexValue = new StringBuilder();
                    for (int i = 0; i < md5Bytes.length; i++) {
                        int val = ((int) md5Bytes[i]) & 0xff;
                        if (val < 16) {
                            hexValue.append("0");
                        }
                        hexValue.append(Integer.toHexString(val));
                    }
                    ret= hexValue.toString().toUpperCase();
                } catch (NoSuchAlgorithmException e) {
                    e.printStackTrace();
                }
            }
            return ret;
        }
    }

    /**
     * 获取Bytes 数组的MD5
     * @param charArray
     * @return
     */
    public static String getBytesMD5(byte[] charArray){
        String ret="";
        if(charArray!=null && charArray.length>0){
            try {
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                byte[] byteArray = new byte[charArray.length];
                for (int i = 0; i < charArray.length; i++) {
                    byteArray[i] = charArray[i];
                }
                byte[] md5Bytes = md5.digest(byteArray);
                StringBuilder hexValue = new StringBuilder();
                for (int i = 0; i < md5Bytes.length; i++) {
                    int val = ((int) md5Bytes[i]) & 0xff;
                    if (val < 16) {
                        hexValue.append("0");
                    }
                    hexValue.append(Integer.toHexString(val));
                }
                ret = hexValue.toString().toUpperCase();
            }catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            }
        }
        return ret;
    }

    @StringDef({ImageType.JPG, ImageType.PNG, ImageType.BITMAP})
    @Retention(RetentionPolicy.SOURCE)
    public @interface ImageType {
        String PNG = ".png";
        String JPG = ".jpg";
        String BITMAP = ".bmp";
    }
}

